//******************************************************************************************
// filename windows.cpp
// implemetion file for windows class
// windows inherit form QMainWindow
// it is the main window
//*****************************************************************************************
#include <QtGui>
#include <QPrintDialog>
#include "window.h"

Window::Window(QWidget *parent) : QMainWindow(parent)
{
   // init eveything
    documentWidget = new DocumentWidget(this);
    // set scale fatctors , -1 for fit windows mode
    scaleFactors <<  0.5 << 0.75 << 1. << 1.25 << 1.5 << 2. << -1;
    setActions();

    // set fast nav panel
    fastNavPanel = new FastNav(this);
    fastNavPanel ->setVisible(false);
    fastViewWidget = new FastViewWidget(this);

    // set widget stack
    widgetStack= new QStackedWidget(this);
    widgetStack->addWidget(documentWidget);
    widgetStack->addWidget(fastNavPanel);
    widgetStack->addWidget(fastViewWidget);
    widgetStack->setCurrentIndex(0);
    setCentralWidget(widgetStack);

    // set side bar
    viewMode = 0;
    thumbnailsDock = new ThumbnailsDock(this);
    sideBar = new QDockWidget(this);
    sideBar-> setAllowedAreas(Qt::LeftDockWidgetArea);
    sideBar-> setFloating (false);
    sideBar-> setWidget(thumbnailsDock);
    sideBar-> setFixedWidth(160);
    addDockWidget(Qt::LeftDockWidgetArea,sideBar);
    // hide side bar title
    QWidget* titleWidget = new QWidget(this); 
    sideBar->setTitleBarWidget( titleWidget );
    sideBar->setVisible(false);
    showSidebar = false;

    // set menu and toolbar
    setMenu();
    setToolBar();

    setWindowTitle("I am test program");

    // connect signals  and slots
    connect(fastNavPanel, SIGNAL(pageChanged(int)), this,SLOT(showPageFromFastNav(int)));
    connect(thumbnailsDock,SIGNAL(currentRowChanged(int)),this,SLOT(showPageFromSidebar(int)));
    connect(fastViewWidget,SIGNAL(midpressed()), this,SLOT(switchFastNav()));
    connect(fastViewWidget,SIGNAL(pageClicked(int)),this,SLOT(findTarget(int)));
    connect(documentWidget,SIGNAL(pageChanged(int)),this,SLOT(updateSideBar(int)));
    connect(documentWidget,SIGNAL(pageClicked(int)),this,SLOT(findTarget(int)));

    //enable mouse tracking
    setMouseTracking(true);
    //init startTest to false
    startTest = false;

    //enable qsrand
    qsrand(QTime::currentTime().msec());

}

// mouse move trackoing
void Window::mouseMoveEvent (QMouseEvent * event)
{
   // track mouse move distance
   if(startTest)
   {
      if(last == QPointF(-1,-1))
	 last = event->globalPos();
      else
      {
	 QPointF current = event->globalPos();
	 QLineF line(last,current);
	 travelDistance += line.length();
	 last = current;
      }
   }
   
}
// even filter
// tracking mouse move for each child
bool Window::eventFilter(QObject *obj, QEvent *event)
{
   if(startTest && event->type() == QEvent::MouseMove &&
      ( obj == scaleComboBox || obj == fastNavButton || obj == testButton
	 || obj == thumbBarButton || obj == abortButton))
   {
      QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
      if(last == QPointF(-1,-1))
	 last = mouseEvent->globalPos();
      else
      {
	 QPointF current = mouseEvent->globalPos();
	 QLineF line(last,current);
	 travelDistance += line.length();
	 last = current;
      }
      return true;
   }
   else
      return QObject::eventFilter(obj, event);
}

void Window::switchMode()
{
   viewMode = (viewMode + 1) % 2;
        
   widgetStack->setCurrentIndex(viewMode);
   // compute time
   if(startTest)
   {
      // if swtich to fast nav view
      int t = timer.elapsed ();
      if(viewMode != 0)
      {
	 // if showed sidebar before
	 if(showSidebar)
	    thumbnailTime += t;
	 docWidgetTime += t;
	 
      }
      // if switch to normal view ( may with thumbnails)
      else if(viewMode == 0)
      	 fastNavTime += t;
      
      // add any time to total test time
      totalTestTime += t;
      timer.restart();
   }

   // if fast nav mode
   // hide thumb bar
   if(viewMode != 0)
   {
      pageSpinBox->setEnabled(false);
      scaleComboBox->setEnabled(false);
      fastNavButton->setText("Normal Mode");
   }
   else
   {
      pageSpinBox->setEnabled(true);
      scaleComboBox->setEnabled(true);
      fastNavButton->setText("FastNav Mode");
   }
   if(viewMode != 0 && showSidebar)
   {
      showSidebar  = !showSidebar;
      sideBar->setVisible(showSidebar);
   }
 
}

//switch to fast Nav
void Window::switchFastNav()
{
  int t =timer.elapsed ();
  timer.restart();
  fastViewTime += t;
  totalTestTime += t;
  widgetStack->setCurrentIndex(1); 
}

// show page from fastNav
void Window::showPageFromFastNav(int pageNumber)
{

    widgetStack->setCurrentIndex(2);
    fastViewWidget->setPage(pageNumber);
    int t = timer.elapsed ();
    timer.restart();
    fastNavTime += t;
    totalTestTime += t;
  
}

// show page from from side bar
void Window::showPageFromSidebar(int pageNumber)
{
   documentWidget->setPage(pageNumber + 1);   
}

// update sideBar
void Window::updateSideBar(int index)
{
   thumbnailsDock -> setCurrentRow(index-1);
}

// slots to show side Bar
void Window::showSideBar()
{
    showSidebar  = !showSidebar;
    sideBar->setVisible(showSidebar);
    if(showSidebar)
       thumbBarButton ->setText("show Thumb");
    else
       thumbBarButton ->setText("hide Thumb");
	  
    if(startTest)
    {
    
       int t = timer.elapsed ();
       // if showed sidebar before
       if(!showSidebar)
	  thumbnailTime += t;
       // if swtich from fast nav view
       if(viewMode != 0)
       	 fastNavTime += t;
     
       // if switch to normal view ( may with thumbnails)
       else if(viewMode == 0)
	  docWidgetTime += t;
	     
      // add any time to total test time
	  totalTestTime += t;
       timer.restart();
      
    }
    // if main widget is not regluar view switch
    if(viewMode != 0 )
       switchMode();
}

// slots to begin Test
void Window::beginTest()
{
   travelDistance = 0.0;
   // init  time data to 0;
   totalTestTime = 0;
   docWidgetTime = 0;
   thumbnailTime = 0;
   fastNavTime = 0;
   fastViewTime = 0;
   
   // reset last point to 0,0
   last.setX(-1);
   last.setY(-1);
  
   //disable and enable ui based on test mode
   if(testMode == 0)
   {
      // normal mode
      showSidebar  = false;
      sideBar->setVisible(showSidebar);
      thumbBarButton -> setEnabled(false);
      fastNavButton -> setEnabled(false);
      if(viewMode != 0 )
	 switchMode();
      documentWidget->setPage(testStart);
   
   }
   else if(testMode == 1)
   {
      // thumbnail bar only
      showSidebar  = true;
      sideBar->setVisible(showSidebar);
      thumbBarButton -> setEnabled(false);
      fastNavButton -> setEnabled(false);
      if(viewMode != 0 )
	 switchMode();
      documentWidget->setPage(testStart);

   
   }
   else if(testMode ==2)
   {
      // fast Nav only
      // disable thumbnails
      showSidebar  = false;
      sideBar->setVisible(showSidebar);
      thumbBarButton -> setEnabled(false);
      fastNavButton -> setEnabled(false);
      if(viewMode != 1)
      {
          viewMode = 1;
          widgetStack->setCurrentIndex(1);
      }
      fastNavPanel->cleanHistory();
   
   }
   else if(testMode == 3)
   {
      //free mode 
      //enable all buttons
      showSidebar  = false;
      sideBar->setVisible(showSidebar);
      thumbBarButton -> setEnabled(true);
      fastNavButton -> setEnabled(true);
      if(viewMode != 0 )
	 switchMode();
      documentWidget->setPage(testStart);
   }
   startTest = true;
   showPageBoxAction->setVisible(false);
   enablePageBoxAction->setChecked(false);
 
   int dx = this->x() + this->frameGeometry().width();
   int dy = this->y(); 
   dialog->move(dx,dy);
   dialog->show();

   // resstart timer after target prev show up
   timer.restart();
   
   testButton->setEnabled(false);
   abortButton->setEnabled(true);
}
// slots to abrot test
void Window::abortTest()
{
   startTest = false;
   testButton->setEnabled(false);
   abortButton->setEnabled(false);
   thumbBarButton -> setEnabled(true);
   fastNavButton -> setEnabled(true);
   dialog->reject();
}

// function to set a test
void Window::setTest()
{
   bool ok = false;

   QStringList items;
   items << tr("Normal Mode") << tr("with Thumbails") << tr("FastNav Mode") << tr("Free");
   ok = false;
   QString item = QInputDialog::getItem(this, tr("Select Test Mode"),
					tr("Test mode"), items, 0, false, &ok);

  
   if(ok)
   {
      testMode = items.indexOf(item);
      testButton->setEnabled(true);

      targetPage = qrand() %  (documentWidget->numPages()-1) + 2; // select from 2 page to last page
      fastNavPanel->setTargetPage(targetPage);

      
      testStart =  0;

      //Not too random but it's fine for this case
      //And I don't know this will case any seg

      testStart =  qrand() % documentWidget->numPages() + 1 ;
      // testStart will be  24.5% to 35 %  document length to start
      if(testStart < (documentWidget->numPages() + 1) * 0.7 )
	 testStart = documentWidget->numPages() +1 - testStart;
      
      testStart = (int)(0.35 * (double)testStart)+1;
      
	 
 
 
     
      int coin = qrand() %  2;
      if( !coin  && testStart < targetPage)
	 testStart = targetPage - testStart;
      else if( coin  && testStart + targetPage <= documentWidget->numPages())
	 testStart += targetPage;
      else if( testStart + targetPage <= documentWidget->numPages())
	 testStart += targetPage;
      else if (testStart < targetPage)
	 testStart = targetPage - testStart;

 
      
      // set target prev
      dialog = new QDialog(this);
      QLabel * tagretlabel = new QLabel("Target Prev",this);
      QVBoxLayout * layout = new  QVBoxLayout(dialog);
      layout->addWidget(tagretlabel);
      QLabel * targetPrev = new QLabel(this);
      targetPrev->setAlignment(Qt::AlignCenter);
      double ratio = (double)documentWidget->getPages()[targetPage-1].width() /documentWidget->getPages()[targetPage-1].height();
      int prevHeight = 800;
 
;
      int prevWidth = (int)((double)prevHeight * ratio);
      
      targetPrev->setPixmap(QPixmap::fromImage(documentWidget->getPages()[targetPage-1].scaled(prevWidth,prevHeight,Qt::IgnoreAspectRatio,Qt::SmoothTransformation)));
      
      layout->addWidget(targetPrev);
      dialog->setLayout(layout);
   }
 
}

// function is used in the test
void Window::findTarget(int pageNumber)
{
   if(pageNumber == targetPage && startTest)
   {
      // compute time first
      int t = timer.elapsed ();
      totalTestTime += t;
      if(testMode != 2)
        docWidgetTime += t;
      else
        fastViewTime += t;
      
      if(showSidebar)
        thumbnailTime = t;
      
      QMessageBox::information(this,"Test finsihed","Target is found , test finished",QMessageBox::Ok,QMessageBox::NoButton);
       
      QFile file("results.txt");
      if (!file.open(QIODevice::WriteOnly|QIODevice::Append)) {
	 QMessageBox::warning(this, "Unable to save", 
			      QString("Cannot write file %1: %2").arg("results.txt").arg(file.errorString()));
	 return ;
      }
      // out put result
      QTextStream out(&file);
      out << "-------------------------------------------------------------------------------------------------" << endl;
      out << "Test Mode: " << testMode << " Finshed time : " << QTime::currentTime().toString() << endl;
      out << "File Name: " << fileName << " Total Pages: " << documentWidget->numPages() << endl;
      out << "Target Page: " << targetPage << endl;
      out << "Start Page: " << testStart << endl;
      out << "total time: " << totalTestTime << "ms. "<< endl;
      out << "total time with doc widget: " << docWidgetTime << " ms. " << endl;
      out << "total time with thumbnail dock: " << thumbnailTime << " ms. " << endl;
      out << "total time in fast Nav Panel: " << fastNavTime << " ms. " << endl;
      out << "total time in fast View Widget: "<< fastViewTime << " ms. " << endl;
      
      out << "Distance traveled in doc widget: "<< documentWidget->getDistance()  << " pixels." << endl;
      out  << "Distance travled in fastNavPanel: " << fastNavPanel->getDistance()  << " pixels." << endl;
      out << "Distance traveled in fastNavView: " << fastViewWidget->getDistance() << " pixels." <<  endl;
      out  << "Distance traveled in thumbnails: " << thumbnailsDock->getDistance() << " pixels." << endl;
      out << "Distance traveled in windowds: " << travelDistance << " pixels." <<  endl;
      
      out << "Page viewed in fastNav Mode: "<<  fastNavPanel->getPreviewTimes() << " times." << endl;
      out << "Target Page viewed in fastNav Mode: "<<  fastNavPanel->getTargetClickTimes() <<" times."<< endl;
      out << "mouse wheel traveled in doc widget " <<  documentWidget->getDegree()  << " degrees." <<  endl;
      out << "Effective mouse wheel traveled in doc widget " <<  documentWidget->getEDegree()  << " degrees." <<  endl;
      out << "Upkey: " <<  documentWidget->getUpKey() << "Downkey: " <<  documentWidget->getDownKey() << " PageUpKey " << documentWidget->getPageUpKey() <<"PageDownKey " <<  documentWidget->getPageDownKey() << endl;
      out << "-------------------------------------------------------------------------------------------------" << endl;
      abortTest();
   }
}


//function to enable pageBox
void Window::enablePageBox()
{
   showPageBoxAction -> setVisible(enablePageBoxAction->isChecked());
}

//function to set actions
void Window::setActions()
{   
   openAction = new QAction("&Open",this);
   openAction->setShortcut(QString("Ctrl+O"));
   openAction->setStatusTip("Open an existing document");
   connect(openAction, SIGNAL(triggered()), this, SLOT(openFile()));
      
   exitAction = new QAction("&Exit",this);
   exitAction->setShortcut(QKeySequence::Close);
   exitAction->setStatusTip("Close program");
   connect(exitAction, SIGNAL(triggered()), this, SLOT(close()));

   setTestAction = new QAction("&Set Test",this);
 
   setTestAction->setStatusTip("set a test");
   connect(setTestAction, SIGNAL(triggered()), this, SLOT(setTest()));
   
   enablePageBoxAction = new QAction("&Show Page Box",this);
   enablePageBoxAction->setStatusTip("show/hide page box");
   enablePageBoxAction->setCheckable(true);
   enablePageBoxAction->setChecked(true);
   connect(enablePageBoxAction, SIGNAL(triggered()), this, SLOT(enablePageBox()));

   statusBar()->show();
}
// function to set menu
void Window::setMenu()
{
   QMenu *fileMenu = menuBar()->addMenu("&File");
   fileMenu->addAction(openAction);
   fileMenu->addAction(exitAction);
   fileMenu->setMouseTracking(true);
   fileMenu->installEventFilter(this);
      
   QMenu *testMenu = menuBar()->addMenu("&Test");
   testMenu->addAction(setTestAction);
   testMenu->addAction(enablePageBoxAction);
   testMenu->setMouseTracking(true);
   testMenu->installEventFilter(this);

}
// function set ToolBar
void Window::setToolBar()
{
   QToolBar *fileToolBar = addToolBar("Control");
   //set page spinBox
   pageSpinBox = new PageSpinBox(this);
   pageSpinBox->setEnabled(false);
 
   showPageBoxAction =  fileToolBar->addWidget(pageSpinBox);
   
   connect(pageSpinBox, SIGNAL(valueChanged(int)), documentWidget, SLOT(setPage(int)));
   connect(documentWidget, SIGNAL(pageChanged(int)), pageSpinBox, SLOT(setValue(int)));

   // set sacle ComboBox
   scaleComboBox = new QComboBox(this);
   scaleComboBox ->setEnabled(false);
   fileToolBar->addWidget(scaleComboBox);

   scaleComboBox->addItem(QString("50%"));
   scaleComboBox->addItem(QString("75%"));
   scaleComboBox->addItem(QString("100%"));
   scaleComboBox->addItem(QString("125%")); 
   scaleComboBox->addItem(QString("150%"));
   scaleComboBox->addItem(QString("200%"));

   scaleComboBox->addItem(QString("Fit Window"));

   scaleComboBox->setCurrentIndex(6);
   connect(scaleComboBox, SIGNAL(currentIndexChanged(int)),this,SLOT(scaleDocument(int)));

   scaleComboBox->installEventFilter(this);

   //set fat Nav Button
   fastNavButton = new QPushButton("FastNav Mode",this);
   connect(fastNavButton, SIGNAL(released ()), this,SLOT(switchMode()));
   fileToolBar->addWidget(fastNavButton);
   fastNavButton-> setMouseTracking(true);
   fastNavButton->installEventFilter(this);
   fastNavButton->setEnabled(false);

   // set thumbBar button
   thumbBarButton = new QPushButton("show thumb",this);
   connect(thumbBarButton, SIGNAL(released ()), this,SLOT(showSideBar()));
   fileToolBar->addWidget(thumbBarButton);
   thumbBarButton-> setMouseTracking(true);
   thumbBarButton->installEventFilter(this);
   thumbBarButton->setEnabled(false);

   // set test button
   testButton = new QPushButton("Start Test",this);
   connect(testButton, SIGNAL(released ()), documentWidget,SLOT(beginTest()));
   connect(testButton, SIGNAL(released ()), fastNavPanel,SLOT(beginTest()));
   connect(testButton, SIGNAL(released ()), thumbnailsDock,SLOT(beginTest()));
   connect(testButton, SIGNAL(released ()), fastViewWidget,SLOT(beginTest()));
   connect(testButton, SIGNAL(released ()), this,SLOT(beginTest()));
   testButton->setEnabled(false);
   fileToolBar->addWidget(testButton);
   testButton-> setMouseTracking(true);
   testButton->installEventFilter(this);

   //set abort test buttom
   abortButton = new QPushButton("Abort",this);
   abortButton->setEnabled(false);
   connect(abortButton, SIGNAL(released ()), documentWidget,SLOT(abortTest()));
   connect(abortButton, SIGNAL(released ()), fastNavPanel,SLOT(abortTest()));
   connect(abortButton, SIGNAL(released ()), thumbnailsDock,SLOT(abortTest()));
   connect(abortButton, SIGNAL(released ()), fastViewWidget,SLOT(abortTest()));
   connect(abortButton, SIGNAL(released ()), this,SLOT(abortTest()));

   fileToolBar->addWidget(abortButton);
   abortButton-> setMouseTracking(true);
   abortButton->installEventFilter(this);
   
}

// function openfile
void Window::openFile()
{
    QString path = QFileDialog::getOpenFileName(this, tr("Open PDF File"),
        lastPath, tr("PDF files (*.pdf)"));

    if (path.isEmpty())
        return;

    if (documentWidget->setDocument(path)) {
       lastPath = path;
      
       if(viewMode == 0)
       {
	  scaleComboBox->setEnabled(true);
	  pageSpinBox->setEnabled(true);
       }
       // set page spinBox
       pageSpinBox->setMinimum(1);
       pageSpinBox->setMaximum(documentWidget->numPages());
       pageSpinBox->setValue(1);
       
       // set fast navpanel , thumbdock and fastview
       fastNavPanel->initDoc(documentWidget->getPages());
       thumbnailsDock ->initDoc(documentWidget->getPages());
       fastViewWidget->setDocument(documentWidget->getDoc());

       //enable and disable child widget
       fastNavButton->setEnabled(true);
       thumbBarButton->setEnabled(true);
       testButton->setEnabled(false);
       //set scale 
       scaleComboBox->setCurrentIndex(6);
       // set title
       fileName = path.right(path.lastIndexOf("/"));
       setWindowTitle(fileName);
    
       connect(fastViewWidget,SIGNAL(pageChanged(int)),documentWidget,SLOT(setPage(int)));
    
    
       
    } else
        QMessageBox::warning(this, tr("PDF Viewer - Failed to Open File"),
                             tr("The specified file could not be opened."));
    //reset test data
    targetPage = 0;
    testMode = 0;

     pageSpinBox->setVisible(true);

    
}
// function to set scale
void Window::scaleDocument(int index)
{
    documentWidget->setScale(scaleFactors[index]);
    
}

